home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 176-200 / disk_185 / examples / display / display.c next >
C/C++ Source or Header  |  1992-05-06  |  25KB  |  913 lines

  1. /*
  2.  * Display v1.06 - 11/88 Carolyn Scheppner   CBM
  3.  *
  4.  *   Read an ILBM file and display as a screen/window until closed.
  5.  *   Simulated close gadget in upper left corner of window.
  6.  *   Clicking below title bar area toggles screen bar for dragging.
  7.  *   Handles normal and HAM ILBM's
  8.  *   Now has options for backscreen, timer, cycling, printing
  9.  *
  10.  *   Options:
  11.  *
  12.  *     opt  b     means come up behind other screens
  13.  *          c     means cycle colors
  14.  *          p     where P means dump to printer
  15.  *          e     default 6 planes to extra-halfbrite
  16.  *          t=n   where n = display time in seconds (without or after dump)
  17.  *
  18.  *  By Carolyn Scheppner   CBM  01/15/88
  19.  *
  20.  *  Modified 09/02/86 - Only global frame is iFrame
  21.  *                      Use message->MouseX and Y
  22.  *                      Wait() for IDCMP
  23.  *  Modified 10/15/86 - For HAM
  24.  *                      Name changed from SeeILBM to ViewILBM
  25.  *  Modified 11/01/86 - Revised for linkage with myreadpict.c
  26.  *  Modified 11/18/86 - For Astartup ... Amiga.lib, LC.lib linkage
  27.  *  Modified 12/12/86 - Added color cycling at request of Mimetics
  28.  *  Modified 01/06/87 - Tab toggles cycling
  29.  *  Modified 03/03/87 - Recognizes RNG_NORATE (36) as non-active DP CRNG
  30.  *                      Changed name to Display
  31.  *  Modified 03/13/87 - Accepts display time in seconds as 2nd CLI arg
  32.  *  Modified 01/15/88 - New command line options, now prints
  33.  *  Modified 04/20/88 - Mask troublesome flags from Viewmodes
  34.  *  Modified 05/06/88 - (v1.04) Add CTRL/D to exit returning failure, e flag
  35.  *  Modified 09/27/88 - (v1.05) Use CAMG, CRNG, and CCRT defs in new ilbm.h
  36.  *  Modified 11/08/88 - (v1.06) Explicitly mask high word of CAMG
  37.  *
  38.  *     Display supports cycling, timed display, printing, and backscreen.
  39.  *     See usage lines. Type Display<RET> or double-click Display for help.
  40.  *     If the command line opt c or picture tooltype CYCLE=TRUE are used,
  41.  *     this viewer will cycle any ILBM that contains cycling chunks
  42.  *     (CCRT or CRNG) which are marked as active and do not have a CRNG
  43.  *     cycle rate of 36. (To DPaint, rate 36 = don't cycle).  Note that
  44.  *     by default, DPaint saves its pics with CRNG (cycling) chunks
  45.  *     flagged as active and with a rate not equal to 36.  
  46.  *
  47.  * Based on ShowILBM.c, readpict.c    1/86
  48.  *  By Jerry Morrison, Steve Shaw, and Steve Hayes, Electronic Arts.
  49.  *  This software is in the public domain.
  50.  *
  51.  * >>NOTE<<: This example must be linked with additional IFF rtn files.
  52.  *           See linkage information below.
  53.  *
  54.  * The display portion is specific to the Commodore Amiga computer.
  55.  *
  56.  * Linkage Information:
  57.  *  (NOTE: All modules including iff stuff compiled with -v on LC2)
  58.  *
  59.  * FROM     LIB:AStartup.obj,Display.o,myreadpict.o,dump.o,iffmsgs.o*
  60.  *          iffr.o,ilbmr.o,unpacker.o
  61.  * TO       Display
  62.  * LIBRARY  LIB:Amiga.lib, LIB:LC.lib
  63.  * 
  64.  */
  65.  
  66. #include <exec/types.h>
  67. #include <exec/memory.h>
  68. #include <exec/tasks.h>
  69. #include <libraries/dos.h>
  70. #include <libraries/dosextens.h>
  71. #include <workbench/startup.h>
  72. #include <workbench/workbench.h>
  73. #include <intuition/intuition.h>
  74. #include <graphics/gfxbase.h>
  75.  
  76. #include "iff/ilbm.h"
  77. #include "myreadpict.h"
  78.  
  79. #ifndef MIN
  80. #define MIN(a,b) ((a)<(b)?(a):(b))
  81. #endif  MIN
  82.  
  83. #define TOUPPER(c)      ((c)>='a'&&(c)<='z'?(c)-'a'+'A':(c)) 
  84.  
  85. /* Bits we must mask out of CAMG.Viewmodes */
  86. #define BADFLAGS  (SPRITES|VP_HIDE|GENLOCK_AUDIO|GENLOCK_VIDEO)
  87. #define FLAGMASK  (~BADFLAGS)
  88. #define CAMGMASK  (FLAGMASK & 0x0000FFFFL)
  89.  
  90. /* The screendump routine */
  91. extern int dump();
  92.  
  93. /* For wbStdio rtns */
  94. extern LONG stdin, stdout, stderr;  /* in Astartup.obj */
  95.  
  96. char conSpec[] = "CON:0/40/640/140/";
  97. BOOL wbHasStdio = NULL;
  98.  
  99.  
  100. /* general usage pointers */
  101. struct GfxBase       *GfxBase;
  102. struct IntuitionBase *IntuitionBase;
  103. ULONG  IconBase = 0;
  104.  
  105. /* Globals for displaying an image */
  106. struct Screen   *screen1;
  107. struct Window   *window1;
  108. struct RastPort *rport1;
  109. struct ViewPort *vport1;
  110.  
  111. struct BitMap   tBitMap;      /* Temp BitMap struct for small pics  */
  112.  
  113. /* For WorkBench startup */    
  114. extern struct WBStartup *WBenchMsg;
  115. struct FileLock *startLock, *newLock;
  116.  
  117. /* Other globals */
  118. BOOL  FromWb, TBtoggle, Done;
  119. BOOL  Cycle=FALSE, Print=FALSE, Timer=FALSE, Back=FALSE, EHB=FALSE;
  120.  
  121. char u1[]  = "\nDISPLAY   v1.06  C. Scheppner  CBM  11/88\n";
  122.  
  123. char u1c[] = "\nCLI Usage: Display ilbmfile [opt [b][c][e][p] [t=n]]\n";
  124. char u2c[] =   "     opts: b=backscreen c=cycle e=ehb p=print t=seconds\n";
  125.  
  126. char u1w[] = "\n WB Usage: Click this icon, SHIFT and DoubleClick on pic\n";
  127. char u2w[] =   "ToolTypes: Display  TIMER=n,PRINT=TRUE,BACK=TRUE\n";
  128. char u3w[] =   "           Picture  CYCLE=TRUE, EHB=TRUE\n";
  129.  
  130. char u2[]  = "\nClick toggles bar, Tab toggles cycling, P prints screen\n";
  131. char u3[]  = "Close upper left or CTRL/C, or CTRL/D to break a script\n";
  132.  
  133. char *cliUsage[] = {u1,u1c,u2c,u2,u3,""};
  134. char *wbUsage[]  = {u1,u1w,u2w,u3w,u2,u3,""};
  135.  
  136. /* Structures for new Screen, new Window */
  137.  
  138. struct   TextAttr       TextFont = {
  139.    "topaz.font",                    /* Font Name   */
  140.    TOPAZ_EIGHTY,                    /* Font Height */
  141.    FS_NORMAL,                       /* Style       */
  142.    FPF_ROMFONT,                     /* Preferences */
  143.    };
  144.  
  145. struct   NewScreen      ns = {
  146.    0, 0,                                  /* LeftEdge and TopEdge   */
  147.    0, 0,                                  /* Width and Height       */
  148.    0,                                     /* Depth                  */
  149.    1, 0,                                  /* DetailPen and BlockPen */
  150.    NULL,                                  /* Special display modes  */
  151.    CUSTOMSCREEN,                          /* Screen Type            */
  152.    &TextFont,                             /* Use my font            */
  153.    " <- Close here after clicking below",                  /* Title */
  154.    NULL,                                  /* No gadgets yet         */
  155.    NULL,                                  /* Ptr to CustomBitmap    */
  156.    };
  157.  
  158. struct   NewWindow      nw = {
  159.    0, 0,                                  /* LeftEdge and TopEdge */
  160.    0, 0,                                  /* Width and Height */
  161.    -1, -1,                                /* DetailPen and BlockPen */
  162.    MOUSEBUTTONS|VANILLAKEY,               /* IDCMP Flags */
  163.    BACKDROP
  164.    |BORDERLESS,                           /* Flags */
  165.    NULL, NULL,                            /* Gadget and Image pointers */
  166.    NULL,                                  /* Title string */
  167.    NULL,                                  /* Put Screen ptr here */
  168.    NULL,                                  /* SuperBitMap pointer */
  169.    0, 0,                                  /* MinWidth and MinHeight */
  170.    0, 0,                                  /* MaxWidth and MaxHeight */
  171.    CUSTOMSCREEN,                          /* Type of window */
  172.    };
  173.  
  174. USHORT  allBlack[maxColorReg] = {0};
  175.  
  176. /* For alloc to define new pointer */
  177. #define PDATASZ 12
  178. UWORD   *pdata;
  179.  
  180. #ifndef MIN
  181. #define MIN(a,b) ((a)<(b)?(a):(b))
  182. #endif  MIN
  183.  
  184. extern char *IFFPMessages[];
  185. ILBMFrame   iFrame;       /* my global frame */
  186.  
  187.  
  188. /* Cycle Task stuff */
  189. #define CYCLETIME  16384L
  190. #define REVERSE    0x02
  191. #define ACTIVE     0x01
  192.  
  193. extern VOID cycleTask();
  194. char *cyTaskName = "CAS_D1.04cyTask";
  195. struct Task *cyTask;
  196.  
  197. /* Data shared with cycle/timer Task */
  198. CRange *cyCrngs;
  199. struct ViewPort *cyVport;
  200. int    cyRegs, cyCnt;
  201. USHORT cyMap[maxColorReg];
  202. LONG   cyClocks[maxCycles];
  203. LONG   cyRates[maxCycles];
  204. LONG   dTimer;
  205. BOOL   TimerOn, CycleOn, PrepareToDie;
  206. struct Task *mainTask;
  207. LONG   tSigNum = -1, retcode = RETURN_OK;
  208. ULONG  tSig;
  209.  
  210. /*
  211.  *  main
  212.  */
  213.  
  214. main(argc, argv)
  215. int argc;
  216. char **argv;
  217.    {
  218.    ULONG           signals, wSig;
  219.    LONG            file;
  220.    IFFP            iffp = NO_FILE;
  221.    struct WBArg    *arg;  
  222.    char            *filename;
  223.    int error;
  224.  
  225.    FromWb = (argc==0) ? TRUE : FALSE;
  226.    TimerOn = FALSE;
  227.  
  228.    if((FromWb)&&(WBenchMsg->sm_NumArgs > 1))
  229.       {
  230.       /* Passed filename via Workbench */
  231.       arg = WBenchMsg->sm_ArgList;
  232.       arg++;
  233.       filename   = (char *)arg->wa_Name;
  234.       newLock    = (struct FileLock *)arg->wa_Lock;
  235.       startLock  = (struct FileLock *)CurrentDir(newLock);
  236.       /* Get ToolTypes */
  237.       getWbOpts(WBenchMsg);
  238.       }
  239.    else if((!FromWb)&&(argc>1)&&(*argv[1] != '?'))
  240.       {
  241.       /* Passed filename via command line */
  242.       filename = argv[1];
  243.  
  244.       if(argc>2)
  245.          {
  246.          if(strEqu(argv[2],"opt"))  getCliOpts(argc,argv);
  247.          else  cleanexit("Bad args\n",RETURN_FAIL);
  248.          }
  249.       }
  250.    else
  251.       {
  252.       usage();
  253.       cleanexit(" ",RETURN_OK); /* Space forces wait for keypress if WB */
  254.       }
  255.  
  256.  
  257.    if(!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0)))
  258.       cleanexit("Can't open graphics",RETURN_FAIL);
  259.  
  260.    if(!(IntuitionBase=
  261.           (struct IntuitionBase *)OpenLibrary("intuition.library",0)))
  262.       cleanexit("Can't open intuition",RETURN_FAIL);
  263.  
  264.    if(!(file = Open(filename, MODE_OLDFILE)))
  265.       cleanexit("Picture file not found",RETURN_WARN);
  266.  
  267.    iffp = myReadPicture(file,&iFrame);
  268.    Close(file);
  269.  
  270.    if (!(iffp == IFF_DONE))
  271.       cleanexit("Not an IFF ILBM",RETURN_WARN);
  272.  
  273.  
  274.    error = DisplayPic(&iFrame);
  275.    if(error)  cleanexit("Can't open screen or window",RETURN_WARN);
  276.  
  277.    if(pdata = (UWORD *)AllocMem(PDATASZ,MEMF_CHIP|MEMF_CLEAR))
  278.       {
  279.       pdata[2] = 0x8000;  /* 1 pixel */
  280.       SetPointer(window1,pdata,1,16,0,0);
  281.       }
  282.  
  283.    /* Set up cycle/timer task */
  284.  
  285.    mainTask = (struct Task *)FindTask(NULL);
  286.    if((tSigNum = AllocSignal(-1)) == -1)
  287.       cleanexit("Can't alloc timerSig",RETURN_FAIL);
  288.    tSig = 1 << tSigNum;
  289.    wSig = 1<<window1->UserPort->mp_SigBit;
  290.  
  291.    initCycle(&iFrame,vport1);
  292.    cyTask = (struct Task *)CreateTask(cyTaskName,0,cycleTask,4000);
  293.    if(!cyTask)  cleanexit("Can't create timimg task",RETURN_FAIL);
  294.  
  295.    /* Dump screen if requested before starting timer */
  296.    if(Print)  dump(screen1);
  297.  
  298.    if(Timer)  TimerOn = TRUE;
  299.    if(Cycle)  CycleOn = TRUE;
  300.  
  301.    TBtoggle   = FALSE;      /* Title bar toggle */
  302.    Done       = FALSE;      /* Close flag       */
  303.  
  304.    while (!Done)
  305.       {
  306.       signals = Wait(SIGBREAKF_CTRL_D|SIGBREAKF_CTRL_C|wSig|tSig);
  307.       if(signals & wSig)  chkmsg();
  308.       if(signals & tSig)  Done = TRUE;
  309.       if(signals & SIGBREAKF_CTRL_C)  Done = TRUE;
  310.       if(signals & SIGBREAKF_CTRL_D)  Done = TRUE, retcode=RETURN_FAIL;
  311.       }
  312.    cleanexit("",retcode);
  313.    }
  314.  
  315.  
  316. getCliOpts(argc,argv)
  317. int  argc;
  318. char **argv;
  319.    {
  320.    int k,i;
  321.    UBYTE c;
  322.  
  323.    for(k=3; k<argc; k++)
  324.       {
  325.       c = argv[k][0] | 0x20;
  326.       switch(c)
  327.          {
  328.          case 't':
  329.             i=0;
  330.             while((argv[k][i])&&(argv[k][i] != '=')) i++;
  331.             i++;
  332.             dTimer = 60 * atoi(&argv[k][i]);
  333.             Timer = TRUE;
  334.             break;
  335.          default:
  336.             for(i=0; argv[k][i]; i++)
  337.                {
  338.                c = argv[k][i] | 0x20;
  339.                switch(c)
  340.                   {
  341.                   case 'b':
  342.                      Back = TRUE;
  343.                      break;
  344.                   case 'p':
  345.                      Print = TRUE;
  346.                      break;
  347.                   case 'c':
  348.                      Cycle = TRUE;
  349.                      break;
  350.                   case 'e':
  351.                      EHB = TRUE;
  352.                      break;
  353.                   default:
  354.                      break;
  355.                   }
  356.                }
  357.  
  358.          }
  359.       }
  360.    }
  361.  
  362.  
  363.  
  364. getWbOpts(wbMsg)
  365. struct WBStartup *wbMsg;
  366.    {
  367.    struct WBArg  *wbArg;
  368.    struct DiskObject *diskobj;
  369.    char **toolarray;
  370.    char *s;
  371.  
  372.    if((IconBase = OpenLibrary("icon.library", 0)))
  373.       {
  374.       /* First get ToolTypes from Display.info */
  375.       wbArg = wbMsg->sm_ArgList;
  376.       diskobj=(struct DiskObject *)GetDiskObject(wbArg->wa_Name);
  377.       if(diskobj)
  378.          {
  379.          toolarray = (char **)diskobj->do_ToolTypes;
  380.  
  381.          if(s=(char *)FindToolType(toolarray,"PRINT"))
  382.             {
  383.             if(strEqu(s,"TRUE"))  Print = TRUE;
  384.             }
  385.          if(s=(char *)FindToolType(toolarray,"BACK"))
  386.             {
  387.             if(strEqu(s,"TRUE"))  Back = TRUE;
  388.             }
  389.          if(s=(char *)FindToolType(toolarray,"TIMER"))
  390.             {
  391.             Timer = TRUE;
  392.             dTimer = 60 * atoi(s);
  393.             }
  394.          FreeDiskObject(diskobj);
  395.          }
  396.  
  397.       if(wbMsg->sm_NumArgs > 1)
  398.          {
  399.          wbArg++;
  400.  
  401.          diskobj=(struct DiskObject *)GetDiskObject(wbArg->wa_Name);
  402.          if(diskobj)
  403.             {
  404.             toolarray = (char **)diskobj->do_ToolTypes;
  405.  
  406.             if(s=(char *)FindToolType(toolarray,"CYCLE"))
  407.                {
  408.                if(strEqu(s,"TRUE"))  Cycle = TRUE;
  409.                }
  410.             if(s=(char *)FindToolType(toolarray,"EHB"))
  411.                {
  412.                if(strEqu(s,"TRUE"))  EHB = TRUE;
  413.                }
  414.             FreeDiskObject(diskobj);
  415.             }
  416.          }
  417.       CloseLibrary(IconBase);
  418.       }
  419.    }
  420.  
  421.  
  422. initCycle(ptFrame,vp)
  423. ILBMFrame *ptFrame;
  424. struct ViewPort *vp;
  425.    {
  426.    int k;
  427.  
  428.    CycleOn  = FALSE;
  429.    PrepareToDie = FALSE;
  430.    cyCrngs  = ptFrame->crngChunks;
  431.    cyVport  = vp;
  432.    cyRegs   = ptFrame->nColorRegs;
  433.    cyCnt    = ptFrame->cycleCnt;
  434.  
  435.    for(k=0; k<cyRegs; k++)
  436.       {
  437.       cyMap[k] = ptFrame->colorMap[k];
  438.       }
  439.  
  440.    /* Init Rates and Clocks */
  441.    for(k=0; k<cyCnt; k++)
  442.       {
  443.       /* In DPaint CRNG, rate = RNG_NORATE (36) means don't cycle */
  444.       if(cyCrngs[k].rate == RNG_NORATE)
  445.          {
  446.          cyCrngs[k].rate = 0;
  447.          cyCrngs[k].active &= ~ACTIVE;
  448.          }
  449.  
  450.       if((cyCrngs[k].active & ACTIVE)&&(cyCrngs[k].rate))
  451.          {
  452.          cyRates[k] = cyCrngs[k].rate;
  453.          }
  454.       else
  455.          {
  456.          cyRates[k] = 0;  /* Means don't cycle to my cycleTask */
  457.          }
  458.       cyClocks[k] = 0;
  459.       }
  460.    }
  461.  
  462.  
  463. VOID cycleTask()
  464.    {
  465.    int    k, i, j;
  466.    UBYTE  low, high;
  467.    USHORT cyTmp;
  468.    BOOL   Cycled;
  469.  
  470.    while(!PrepareToDie)
  471.       {
  472.       WaitTOF();
  473.       if(CycleOn)
  474.          {
  475.          Cycled = FALSE;
  476.          for(k=0; k<cyCnt; k++)
  477.             {
  478.             if(cyRates[k])  /* cyRate 0 = inactive */
  479.                {
  480.                cyClocks[k] += cyRates[k];
  481.                if(cyClocks[k] >= CYCLETIME)
  482.                   {
  483.                   Cycled = TRUE;
  484.                   cyClocks[k] -= CYCLETIME;
  485.                   low = cyCrngs[k].low;
  486.                   high= cyCrngs[k].high;
  487.                   if(cyCrngs[k].active & REVERSE)  /* Reverse cycle */
  488.                      {
  489.                      cyTmp = cyMap[low];
  490.                      for(i=low,j=low+1; i < high; i++,j++)
  491.                         {
  492.                         cyMap[i] = cyMap[j];
  493.                         }
  494.                      cyMap[high] = cyTmp;
  495.                      }
  496.                   else     /* Forward cycle */
  497.                      {
  498.                      cyTmp = cyMap[high];
  499.                      for(i=high,j=high-1; i > low; i--,j--)
  500.                         {
  501.                         cyMap[i] = cyMap[j];
  502.                         }
  503.                      cyMap[low] = cyTmp;
  504.                      }
  505.                   }
  506.                }
  507.             }
  508.          if(Cycled)
  509.             {
  510.             LoadRGB4(cyVport,cyMap,cyRegs);
  511.             }
  512.          }
  513.       if(TimerOn)
  514.          {
  515.          if(--dTimer <= 0)  Signal(mainTask,tSig);
  516.          }
  517.       }
  518.    PrepareToDie = FALSE;
  519.    Wait(0L);  /* Wait to die */
  520.    }
  521.  
  522.  
  523. chkmsg()
  524.    {
  525.    struct IntuiMessage *msg;
  526.    ULONG class, code;
  527.    SHORT mouseX, mouseY;
  528.  
  529.    while(msg=(struct IntuiMessage *)GetMsg(window1->UserPort))
  530.       {
  531.       class = msg->Class;
  532.       code  = msg->Code;
  533.       mouseX = msg->MouseX;
  534.       mouseY = msg->MouseY;
  535.  
  536.       ReplyMsg(msg);
  537.       switch(class)
  538.          {
  539.          case MOUSEBUTTONS:
  540.             if ((code == SELECTDOWN)&&
  541.                   (mouseX < 10)&&(mouseY<10))
  542.                {
  543.                Done = TRUE;
  544.                }
  545.             else if ((code == SELECTDOWN)&&
  546.                        ((mouseY>10)||(mouseX>10))&&
  547.                           (TBtoggle==FALSE))
  548.                {
  549.                TBtoggle = TRUE;
  550.                ShowTitle(screen1,TRUE);
  551.                ClearPointer(window1);
  552.                }
  553.             else if ((code == SELECTDOWN)&&
  554.                        (mouseY>10)&&(TBtoggle==TRUE))
  555.                {
  556.                TBtoggle = FALSE;
  557.                ShowTitle(screen1,FALSE);
  558.                SetPointer(window1,pdata,1,16,0,0);
  559.                }
  560.             break;
  561.          case VANILLAKEY:
  562.             switch(code)
  563.                {
  564.                case 0x03:    /* CTRL/C */
  565.                   Done = TRUE;
  566.                   break;
  567.                case 0x04:    /* CTRL/D */
  568.                   Done = TRUE;
  569.                   retcode = RETURN_FAIL;
  570.                   break;
  571.                case 'p': case 'P':
  572.                   dump(screen1);
  573.                   break;
  574.                case 0x09:    /* Tab toggles Cycle */
  575.                   if(CycleOn)
  576.                      {
  577.                      CycleOn = FALSE;
  578.                      WaitTOF();        /* Make sure cyTask saw FALSE */
  579.                      WaitBOVP(vport1);
  580.                      LoadRGB4(vport1,iFrame.colorMap,maxColorReg);
  581.                      }
  582.                   else
  583.                      {
  584.                      initCycle(&iFrame,vport1);
  585.                      CycleOn = TRUE;
  586.                      }
  587.                   break;
  588.                default:
  589.                   break;
  590.                }
  591.             break;
  592.          default:
  593.             break;
  594.          }
  595.       }
  596.    }
  597.  
  598.  
  599. usage()
  600.    {
  601.    char **ulines;
  602.    int k;
  603.  
  604.    if((FromWb)&&(! wbHasStdio))  wbHasStdio = openStdio(conSpec);
  605.  
  606.    if((!FromWb)||(wbHasStdio))
  607.       {
  608.       ulines = FromWb ? wbUsage : cliUsage;
  609.       for(k=0; ulines[k][0]; k++)
  610.          {
  611.          Write(stdout,ulines[k],strlen(ulines[k]));
  612.          }
  613.       }
  614.    }
  615.  
  616.  
  617. cleanexit(s,rcode)
  618. char  *s;
  619. LONG  rcode;
  620.    {
  621.    if(*s)
  622.       {
  623.       if((FromWb)&&(!wbHasStdio))  wbHasStdio = openStdio(conSpec);
  624.  
  625.       if((!FromWb)||(wbHasStdio))
  626.          {
  627.          Write(stdout,s,strlen(s));
  628.          Write(stdout,"\n",1);
  629.          }
  630.       if(wbHasStdio)
  631.          {
  632.          Write(stdout,"\nPRESS RETURN TO EXIT\n",22);
  633.          while (getchar() != '\n');
  634.          }
  635.       }
  636.    cleanup();
  637.    if(wbHasStdio) closeStdio();
  638.    exit(rcode);
  639.    }
  640.  
  641.  
  642. cleanup()
  643.    {
  644.    struct IntuiMessage *msg;
  645.  
  646.    if(cyTask)
  647.       {
  648.       CycleOn = FALSE;
  649.       PrepareToDie = TRUE;
  650.       while(PrepareToDie)  Delay(10);
  651.       DeleteTask(cyTask);
  652.       }
  653.  
  654.    /* Free timer signal */
  655.    if (tSigNum > -1)  FreeSignal(tSigNum);
  656.  
  657.    /* Note - tBitMap planes were deallocated in DisplayPic() */
  658.    if (window1)
  659.       {
  660.       while(msg=(struct IntuiMessage *)GetMsg(window1->UserPort))
  661.          {
  662.          ReplyMsg(msg);
  663.          }
  664.       CloseWindow(window1);
  665.       }
  666.    if (screen1) CloseScreen(screen1);
  667.    if (pdata)   FreeMem(pdata,PDATASZ);
  668.    if (IntuitionBase) CloseLibrary(IntuitionBase);
  669.    if (GfxBase)       CloseLibrary(GfxBase);
  670.    if (newLock != startLock)  CurrentDir(startLock);
  671.    }
  672.  
  673.  
  674. strlen(s)
  675. char *s;
  676.    {
  677.    int i = 0;
  678.    while(*s++) i++;
  679.    return(i);
  680.    }
  681.  
  682.  
  683.  
  684. /** getBitMap() *********************************************************
  685.  *
  686.  * Open screen or temp bitmap.
  687.  *   Returns ptr destBitMap  or  0 = error
  688.  *
  689.  *************************************************************************/
  690. struct BitMap *getBitMap(ptilbmFrame)
  691.    ILBMFrame *ptilbmFrame;
  692.    {
  693.    int     i, nPlanes, plsize;
  694.    SHORT  sWidth, sHeight, dWidth, dHeight;
  695.    struct BitMap *destBitMap;
  696.  
  697.    sWidth  = ptilbmFrame->bmHdr.w;
  698.    sHeight = ptilbmFrame->bmHdr.h;
  699.    dWidth  = ptilbmFrame->bmHdr.pageWidth;
  700.    dHeight = ptilbmFrame->bmHdr.pageHeight;
  701.    nPlanes = MIN(ptilbmFrame->bmHdr.nPlanes, EXDepth);
  702.  
  703.    ns.Width  = dWidth;
  704.    ns.Height = dHeight;
  705.    ns.Depth  = nPlanes;
  706.  
  707.    if (ptilbmFrame->foundCAMG)
  708.       {
  709.       ns.ViewModes = ptilbmFrame->camgChunk.ViewModes & CAMGMASK;
  710.       }
  711.    else
  712.       {
  713.       if (ptilbmFrame->bmHdr.pageWidth >= 640)
  714.          ns.ViewModes = HIRES;
  715.       else
  716.          ns.ViewModes = 0;
  717.  
  718.       if (ptilbmFrame->bmHdr.pageHeight >= 400)
  719.          ns.ViewModes |= LACE;
  720.  
  721.       /* EHB is kludgey flag for ExtraHalbrite ILBMs with no CAMG */
  722.       if(ns.Depth == 6)
  723.          {
  724.          if(EHB) ns.ViewModes |= EXTRA_HALFBRITE;
  725.          else ns.ViewModes |= HAM;
  726.          }
  727.       }
  728.    
  729.  
  730.    if(Back) ns.Type |= SCREENBEHIND;
  731.    
  732.    if ((screen1 = (struct Screen *)OpenScreen(&ns))==NULL)    return(0);
  733.  
  734.    vport1 = &screen1->ViewPort;
  735.    LoadRGB4(vport1, &allBlack[0], MIN(1<<ns.Depth,maxColorReg));
  736.  
  737.    if((ns.ViewModes)&(HAM))  setHam(screen1,FALSE);
  738.  
  739.    nw.Width  = dWidth;
  740.    nw.Height = dHeight;
  741.    nw.Screen = screen1;
  742.  
  743.    if(!Back)  nw.Flags |= ACTIVATE;
  744.  
  745.    if ((window1 = (struct Window *)OpenWindow(&nw))==NULL)
  746.       {
  747.       CloseScreen(screen1);
  748.       screen1 = NULL;
  749.       return(0);
  750.       }
  751.  
  752.    ShowTitle(screen1, FALSE);
  753.  
  754.    if ((sWidth == dWidth) && (sHeight == dHeight))
  755.       {
  756.       destBitMap = (struct BitMap *)screen1->RastPort.BitMap;
  757.       }
  758.    else
  759.       {
  760.       InitBitMap( &tBitMap,
  761.                   nPlanes,
  762.                   sWidth,
  763.                   sHeight);
  764.  
  765.       plsize = RowBytes(ptilbmFrame->bmHdr.w) * ptilbmFrame->bmHdr.h;
  766.       if (tBitMap.Planes[0] =
  767.        (PLANEPTR)AllocMem(nPlanes * plsize, MEMF_CHIP))
  768.          {
  769.          for (i = 1; i < nPlanes; i++)
  770.             tBitMap.Planes[i] = (PLANEPTR)tBitMap.Planes[0] + plsize*i;
  771.          destBitMap = &tBitMap;
  772.          }
  773.       else
  774.          {
  775.          CloseWindow(window1);
  776.          window1 = NULL;
  777.          CloseScreen(screen1);
  778.          screen1 = NULL;
  779.          return(0);  /* can't allocate temp BitMap */
  780.          }
  781.       }
  782.    return(destBitMap);          /* destBitMap allocated */
  783.    }
  784.  
  785.  
  786. /** DisplayPic() *********************************************************
  787.  *
  788.  * Display loaded bitmap.  If tBitMap, first transfer to screen.
  789.  *
  790.  *************************************************************************/
  791. DisplayPic(ptilbmFrame)
  792.    ILBMFrame *ptilbmFrame;
  793.    {
  794.    int    i, row, byte, nrows, nbytes;
  795.    struct BitMap  *tbp, *sbp; /* temp and screen BitMap ptrs */
  796.    UBYTE  *tpp, *spp;         /* temp and screen plane ptrs  */
  797.  
  798.    if (tBitMap.Planes[0])     /* transfer from tBitMap if nec. */
  799.       {
  800.       tbp = &tBitMap;
  801.       sbp = screen1->RastPort.BitMap;
  802.       nrows  = MIN(tbp->Rows, sbp->Rows);
  803.       nbytes = MIN(tbp->BytesPerRow, sbp->BytesPerRow);
  804.  
  805.       for (i = 0; i < sbp->Depth; i++)
  806.          {
  807.          tpp = (UBYTE *)tbp->Planes[i];
  808.          spp = (UBYTE *)sbp->Planes[i];
  809.          for (row = 0; row < nrows; row++)
  810.             {
  811.             tpp = tbp->Planes[i] + (row * tbp->BytesPerRow);
  812.             spp = sbp->Planes[i] + (row * sbp->BytesPerRow);
  813.             for (byte = 0; byte < nbytes; byte++)
  814.                {
  815.                *spp++ = *tpp++;
  816.                }
  817.             }
  818.          }
  819.       /*  Can now deallocate the temp BitMap  */
  820.       FreeMem(tBitMap.Planes[0],
  821.                  tBitMap.BytesPerRow * tBitMap.Rows * tBitMap.Depth);
  822.       }
  823.  
  824.    vport1 = &screen1->ViewPort;
  825.    LoadRGB4(vport1, ptilbmFrame->colorMap, ptilbmFrame->nColorRegs);
  826.    if((ns.ViewModes)&(HAM))  setHam(screen1,TRUE);
  827.  
  828.    return(0);
  829.    }
  830.  
  831.  
  832. /* setHam --- For toggling HAM so HAM pic invisible while loading */
  833. setHam(scr,toggle)
  834. struct Screen *scr;
  835. BOOL   toggle;
  836.    {
  837.    struct ViewPort *vp;
  838.    struct View     *v;
  839.  
  840.    vp = &(scr->ViewPort);
  841.    v = (struct View *)ViewAddress();
  842.    Forbid();
  843.    if(toggle)
  844.       {
  845.       v->Modes  |= HAM;
  846.       vp->Modes |= HAM;
  847.       }
  848.    else
  849.       {
  850.       v->Modes  &= ~HAM;
  851.       vp->Modes &= ~HAM;
  852.       }
  853.    MakeScreen(scr);
  854.    RethinkDisplay();
  855.    Permit();
  856.    }
  857.  
  858. strEqu(p, q) 
  859. TEXT *p, *q; 
  860.    { 
  861.    while(TOUPPER(*p) == TOUPPER(*q))
  862.       {
  863.       if (*(p++) == 0)  return(TRUE);
  864.       ++q; 
  865.       }
  866.    return(FALSE);
  867.    } 
  868.  
  869. /* wbStdio.c --- Open an Amiga stdio window under workbench
  870.  *               For use with AStartup.obj
  871.  */
  872.  
  873. openStdio(conspec)
  874. char *conspec;
  875.    {
  876.    LONG wfile;
  877.    struct Process *proc;
  878.    struct FileHandle *handle;
  879.  
  880.    if (wbHasStdio)  return(1);
  881.  
  882.    if (!(wfile = Open(conspec,MODE_NEWFILE)))  return(0);
  883.    stdin  = wfile;
  884.    stdout = wfile;
  885.    stderr = wfile;
  886.    handle = (struct FileHandle *)(wfile << 2);
  887.    proc = (struct Process *)FindTask(NULL);
  888.  
  889.    proc->pr_ConsoleTask = (APTR)(handle->fh_Type);
  890.    proc->pr_CIS = (BPTR)stdin;
  891.    proc->pr_COS = (BPTR)stdout;
  892.    return(1);
  893.    }
  894.  
  895. closeStdio()
  896.    {
  897.    struct Process *proc;
  898.    struct FileHandle *handle;
  899.  
  900.    if (! wbHasStdio) return(0);
  901.  
  902.    if (stdin > 0)  Close(stdin);
  903.    stdin  = -1;
  904.    stdout = -1;
  905.    stderr = -1;
  906.    handle = (struct FileHandle *)(stdin << 2);
  907.    proc = (struct Process *)FindTask(NULL);
  908.    proc->pr_ConsoleTask = NULL;
  909.    proc->pr_CIS = NULL;
  910.    proc->pr_COS = NULL;
  911.    wbHasStdio = NULL;
  912.    }
  913.